<?php
/**
 * Created by PhpStorm.
 * User: Admin
 * Date: 2020-08-02
 * Time: 上午 11:13
 */
namespace Lib;

require_once'di.php';
require_once'injector.php';

/**
 * Class Core
 * @package Lib
 * 
 * @property-read \Lib\Functions $fns
 * @property-read \Lib\Config $config
 */
class Core extends Injector {
    protected $_cmdOptions;

    public function __construct() {
    }

    public function rootPath($path='') {
        return $this->fns->formatPath(dirname(dirname(__dir__)) . '/' . implode('/', func_get_args()));
    }

    public function actionPath() {
        return $this->rootPath('core/action', implode('/', func_get_args()));
    }
    
    public function cmdPath() {
        return $this->rootPath('core/cmd', implode('/', func_get_args()));
    }

    public function viewPath() {
        return $this->rootPath('core/view', implode('/', func_get_args()));
    }

    public function libPath() {
        return $this->rootPath('core/lib', implode('/', func_get_args()));
    }
    
    public function varPath() {
        return $this->rootPath('var', implode('/', func_get_args()));
    }

    public function sessionsPath() {
        return $this->varPath('sessions', implode('/', func_get_args()));
    }

    public function storagePath() {
        return $this->varPath('storage', implode('/', func_get_args()));
    }

    public function action($action) {
        $action = $this->fns->formatPath($action);
        $actionNamespace = dirname($action);
        $actionNamespace = $actionNamespace == '.' ? '' : $actionNamespace;
        $action = basename($action);
        $actionClass = array_map('ucfirst', explode('-', $action));
        // $actionClass []= 'Action';
        $namespace = str_replace('/', '\\',  $actionNamespace);
        $namespace = $namespace ? "$namespace\\" : $namespace;
        $actionClass = "\Action\\" . ucwords($namespace, '/') . implode('', $actionClass);
        // $actionPath = $this->actionPath("$actionNamespace/$action.php");
        
        // if(!file_exists($actionPath)) {
        //     $this->actionNotfound($action);
        // }
        //
        // require_once $actionPath;
        
        if(!class_exists($actionClass)) {
            $this->actionNotfound($action);
        }

        $actionInstance = di()->get($actionClass);

        if(!$actionInstance instanceof \Lib\Action) {
            $this->actionNotfound($action);
        }

        $actionInstance->main();
        exit;
    }
    
    public function cmd($scriptName, $options=null) {
        $cmd = $this->fns->formatPath($scriptName);
        $cmdNamespace = dirname($cmd);
        $cmdNamespace = $cmdNamespace == '.' ? '' : $cmdNamespace;
        $cmd = basename($cmd);
        $actionClass = array_map('ucfirst', explode('-', $cmd));
        // $actionClass []= 'Cmd';
        $namespace = str_replace('/', '\\',  $cmdNamespace);
        $namespace = $namespace ? "$namespace\\" : $namespace;
        $actionClass = "\Cmd\\" . ucwords($namespace, '/') . implode('', $actionClass);
        $cmdPath = $this->cmdPath("$cmdNamespace/$cmd.php");

        if(!file_exists($cmdPath)) {
            echo "不支持的命令 '$scriptName'" . PHP_EOL;
            die;
        }

        require_once $cmdPath;

        if(!class_exists($actionClass)) {
            echo "未找到命令的执行类 '$actionClass'" . PHP_EOL;
            die;
        }

        $cmdInstance = di()->get($actionClass);

        if(!$cmdInstance instanceof \Lib\Cmd) {
            echo "无法识别的命令 '$scriptName'" . PHP_EOL;
            die;
        }
        
        $cmdInstance->prepareParams($options);
        
        if($cmdInstance->existParam('help')) {
            $cmdInstance->help();
        } else {
            $cmdInstance->main();
        }
        
        exit;
    }
    
    public function actionNotfound($action='') {
        if($action == 'notfound') {
            echo "404 not found";
            die;
        }
        
        $this->action('notfound');
    }
    
    public function redirectToAction($action, $params=[]) {
        $this->fns->redirectTo($this->actionUrl($action, $params));
    }
    
    public function actionUrl($action, $params=[]) {
        if($action == 'index') {
            return '/';
        }
        
        $params ['a']= $action;
        return '/?' . http_build_query($params);
    }

    /**
     * @param null $key
     * @return Config
     */
    public function config($key=null) {
        if(null !== $key) {
            return $this->config->get($key);
        } else {
            return $this->config;
        }
    }
    
    public function internalPath() {
        return $this->rootPath($this->getInternalName(), implode('/', func_get_args()));
    }
    
    public function getInternalName() {
        return $this->config('internal_name');
    }
    
    public function internalUrl($path, $params=[]) {
        return 
            "/{$this->getInternalName()}/" 
            . $this->fns->calcRelativePath($this->internalPath(), $path)
            .(empty($params) ? '' : ('?' . http_build_query($params)))
        ;
    }
    
    /**
     * 获取命令行参数
     * @return array[]
     */
    public function getCmdOptions() {
        if(isset($this->_cmdOptions)) {
            return $this->_cmdOptions;
        }
        
        $argv = $_SERVER['argv'];
        unset($argv[0]);
        $argv = array_values($argv);
        
        $cmdOptions = [
            'argv' => [],
            'params' => []
        ];

        //执行cmd的命令
        if($argv[0][0] == '-') {
            $cmdOptions['argv'][0] = '';
        } else {
            $cmdOptions['argv'][0] = $argv[0];
            array_splice($argv, 0, 1);
        }

        $argc = count($argv);
        
        //解析命令行参数
        for($i=0; $i<$argc; $i++) {
            $arg = $argv[$i];

            if('--' == $arg) {
                $cmdOptions['argv'] []= implode(' ', array_slice($argv, $i+1));
                break;
            }

            if(preg_match('#^-[0-9]+$#', $arg)) {
                $cmdOptions['params'] ['-'] = trim($arg, '-');
                continue;
            }

            if(substr($arg, 0, 2) == '--') {
                list($k, $v) = explode('=', ltrim($arg, '-'), 2);

                if(null == $v && $argv[$i+1][0] != '-') {
                    $cmdOptions['params'][$k] = $argv[$i+1];
                    $i++;
                } else {
                    $cmdOptions['params'][$k] = $v;
                }

                continue;
            }

            if($arg[0] == '-') {
                if($arg == '-') {
                    continue;
                }

                $cmdOptions['params'] = array_merge($cmdOptions['params'], array_map(function(){return true;}, array_flip(str_split(trim($arg, '-')))));
                continue;
            }

            $cmdOptions['argv'] []= $arg;
        }
        
        return $this->_cmdOptions = $cmdOptions;
    }
    
    public static function  registerAutoLoad() {
        spl_autoload_register(function($class) {
            $class = '\\' . ltrim($class, '\\');
            $class = str_replace("\\", '/', strtolower($class));
            $classFile = dirname(__DIR__) . $class . '.php';
            
            if(file_exists($classFile)) {
                require_once $classFile;
            }
        });
    }
}

// $CORE = new Core;